package ginplus

import (
	"errors"
	"fmt"
	"gitee.com/hongzhaomin/hzm-common-go/strutil"
	"reflect"
	"strconv"
	"strings"
)

func getTypeName(tp any) (name string, fullPathName string) {
	rt := reflect.Indirect(reflect.ValueOf(tp)).Type()
	name = rt.Name()
	fullPathName = strings.Join([]string{rt.PkgPath(), name}, strutil.Slash)
	return
}

func getFullPathTypeName(rt reflect.Type) string {
	if rt.Kind() == reflect.Ptr {
		rt = rt.Elem()
	}
	return strings.Join([]string{rt.PkgPath(), rt.Name()}, strutil.Slash)
}

func mustPoint(a any) {
	rt := reflect.TypeOf(a)
	// 因为我下面需要对结构体设值，所以这里接收的必须是指针
	if rt.Kind() != reflect.Ptr {
		msg := fmt.Sprintf("[%s]不是指针类型", rt.Name())
		panic(msg)
	}
}

func basicConvert4Interface(rt reflect.Type, val any) reflect.Value {
	var valStr string
	switch act := val.(type) {
	case int:
		valStr = strconv.FormatInt(int64(act), 10)
	case int8:
		valStr = strconv.FormatInt(int64(act), 10)
	case int16:
		valStr = strconv.FormatInt(int64(act), 10)
	case int32:
		valStr = strconv.FormatInt(int64(act), 10)
	case int64:
		valStr = strconv.FormatInt(act, 10)
	case uint:
		valStr = strconv.FormatInt(int64(act), 10)
	case uint8:
		valStr = strconv.FormatInt(int64(act), 10)
	case uint16:
		valStr = strconv.FormatInt(int64(act), 10)
	case uint32:
		valStr = strconv.FormatInt(int64(act), 10)
	case uint64:
		valStr = strconv.FormatInt(int64(act), 10)
	case float64:
		valStr = strconv.FormatFloat(act, 'f', -1, 64)
	case float32:
		valStr = strconv.FormatFloat(float64(act), 'f', -1, 32)
	case bool:
		valStr = strconv.FormatBool(act)
	case string:
		valStr = act
	}
	return basicConvert(rt, valStr)
}

func basicConvert(rt reflect.Type, p string) reflect.Value {
	if rt.Kind() == reflect.Ptr {
		rt = rt.Elem()
	}
	switch rt.Kind() {
	case reflect.String:
		return reflect.ValueOf(&p)
	case reflect.Int:
		pInt := str2Int(p)
		return reflect.ValueOf(&pInt)
	case reflect.Int8:
		pInt8 := int8(str2Int64(p))
		return reflect.ValueOf(&pInt8)
	case reflect.Int16:
		pInt16 := int16(str2Int64(p))
		return reflect.ValueOf(&pInt16)
	case reflect.Int32:
		pInt32 := int32(str2Int64(p))
		return reflect.ValueOf(&pInt32)
	case reflect.Int64:
		pInt64 := str2Int64(p)
		return reflect.ValueOf(&pInt64)
	case reflect.Uint:
		pUint := uint(str2Uint64(p))
		return reflect.ValueOf(&pUint)
	case reflect.Uint8:
		pUint8 := uint8(str2Uint64(p))
		return reflect.ValueOf(&pUint8)
	case reflect.Uint16:
		pUint16 := uint16(str2Uint64(p))
		return reflect.ValueOf(&pUint16)
	case reflect.Uint32:
		pUint32 := uint32(str2Uint64(p))
		return reflect.ValueOf(&pUint32)
	case reflect.Uint64:
		pUint64 := str2Uint64(p)
		return reflect.ValueOf(&pUint64)
	case reflect.Float32:
		pFloat32 := float32(str2Float64(p))
		return reflect.ValueOf(&pFloat32)
	case reflect.Float64:
		pFloat64 := str2Float64(p)
		return reflect.ValueOf(&pFloat64)
	case reflect.Bool:
		var pBool bool
		if strutil.IsBlank(p) {
			return reflect.ValueOf(&pBool)
		}
		pBool, err := strconv.ParseBool(p)
		if err != nil {
			panic(errors.New("类型转换异常" + err.Error()))
		}
		return reflect.ValueOf(&pBool)
	default:
		panic(errors.New("无法转换的数据类型"))
	}
}

func str2Int(p string) int {
	var pInt int
	if strutil.IsBlank(p) {
		return pInt
	}
	pInt, err := strconv.Atoi(p)
	if err != nil {
		panic(errors.New("类型转换异常" + err.Error()))
	}
	return pInt
}

func str2Int64(p string) int64 {
	var pInt64 int64
	if strutil.IsBlank(p) {
		return pInt64
	}
	pInt64, err := strconv.ParseInt(p, 10, 64)
	if err != nil {
		panic(errors.New("类型转换异常" + err.Error()))
	}
	return pInt64
}

func str2Uint64(p string) uint64 {
	var pUint64 uint64
	if strutil.IsBlank(p) {
		return pUint64
	}
	pUint64, err := strconv.ParseUint(p, 10, 64)
	if err != nil {
		panic(errors.New("类型转换异常" + err.Error()))
	}
	return pUint64
}

func str2Float64(p string) float64 {
	var pFloat64 float64
	if strutil.IsBlank(p) {
		return pFloat64
	}
	pFloat64, err := strconv.ParseFloat(p, 64)
	if err != nil {
		panic(errors.New("类型转换异常" + err.Error()))
	}
	return pFloat64
}

// 首字母大写
func firstLetter2Upper(str string) string {
	sLen := len(str)
	if sLen == 0 {
		return ""
	}
	newSli := make([]byte, 0, sLen)
	firstChar := str[0]
	if isLower := firstChar >= 'a' && firstChar <= 'z'; isLower {
		firstChar -= 'a' - 'A'
		newSli = append(newSli, firstChar)
	}
	if sLen > 1 {
		newSli = append(newSli, str[1:]...)
	}
	return string(newSli)
}

func SpitCommaAndTrim(str string) []string {
	var strs []string
	for _, s := range strings.Split(str, strutil.Comma) {
		s = strings.Trim(s, " ")
		if strutil.IsNotBlank(s) {
			strs = append(strs, s)
		}
	}
	return strs
}
